package com.sqbang.dbcompare.controller;

import com.sqbang.dbcompare.aop.AuthorityCheck;
import com.sqbang.dbcompare.biz.DifferentDataBiz;
import com.sqbang.dbcompare.biz.GeneratorBiz;
import com.sqbang.dbcompare.biz.DifferentStructBiz;
import com.sqbang.dbcompare.constant.SystemConstant;
import com.sqbang.dbcompare.constant.enums.RegulationCheckTypeEnum;
import com.sqbang.dbcompare.pojo.bo.CheckReportBo;
import com.sqbang.dbcompare.pojo.bo.DifferentReportBo;
import com.sqbang.dbcompare.pojo.cache.CommonData;
import com.sqbang.dbcompare.pojo.dto.DatabaseInfoDto;
import com.sqbang.dbcompare.pojo.model.BizException;
import com.sqbang.dbcompare.pojo.model.R;
import com.sqbang.dbcompare.pojo.vo.DatabaseInfoVo;
import com.sqbang.dbcompare.pojo.vo.GeneratorInfoVo;
import com.sqbang.dbcompare.util.Tools;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 生成sql的参考：https://gitee.com/bravof/differ
 */

/**
 * 主要的控制器
 * @author suqiongbang
 * @date 2020/12/28 20:33
 */
@RestController
@RequestMapping("/api")
@AuthorityCheck
public class ApiController {

    @Autowired
    DifferentStructBiz differentStructBiz;

    @Autowired
    DifferentDataBiz differentDataBiz;

    @Autowired
    GeneratorBiz generatorBiz;

    @GetMapping("/test")
    public R<Boolean> test() {
        return R.ok(true);
    }

    @PostMapping("/auth")
    @AuthorityCheck(flag = false)
    public R<String> auth(@RequestBody Map<String, Object> param) {
        String authCode = (String) param.get("authCode");
        if (StringUtils.isEmpty(authCode)) {
            throw new BizException(HttpStatus.BAD_REQUEST, "授权码不能为空");
        }
        if (!CommonData.authCode.equals(authCode)) {
            throw new BizException(HttpStatus.BAD_REQUEST, "授权码不正确");
        }
        return R.ok();
    }

    @GetMapping("/list")
    public R<List<DatabaseInfoDto>> list() {
        return R.ok(CommonData.databaseInfoList);
    }

    @GetMapping("/listRegulationCheckType")
    public R<List<Map<String, String>>> listRegulationCheckType() {
        List<Map<String, String>> resultList = new ArrayList<>();
        for (RegulationCheckTypeEnum regulationCheckTypeEnum : RegulationCheckTypeEnum.values()) {
            Map<String, String> result = new HashMap<>(4);
            result.put("code", regulationCheckTypeEnum.getCode());
            result.put("desc", regulationCheckTypeEnum.getDesc());
            resultList.add(result);
        }
        return R.ok(resultList);
    }

    @GetMapping("/getIgnoreWords")
    public R<String> getIgnoreWords(String code) {
        if (RegulationCheckTypeEnum.NAME_ERROR_SPELL.getCode().equals(code)) {
            return R.ok(CommonData.ignoreSpellingWordStr);
        } else if (RegulationCheckTypeEnum.TABLE_NAME_CONTAIN_PLURALITY.getCode().equals(code)) {
            return R.ok(CommonData.ignorePluralizeWordStr);
        }
        return R.ok();
    }

    @PostMapping("/save")
    public R<Boolean> save(@RequestBody DatabaseInfoVo databaseInfoVo) {
        if (databaseInfoVo.getKey() == null || databaseInfoVo.getKey() < 0) {
            DatabaseInfoDto target = new DatabaseInfoDto();
            BeanUtils.copyProperties(databaseInfoVo, target);
            CommonData.databaseInfoList.add(target);
        } else {
            DatabaseInfoDto databaseInfoDto = CommonData.databaseInfoList.get(databaseInfoVo.getKey());
            BeanUtils.copyProperties(databaseInfoVo, databaseInfoDto);
        }
        Tools.setCacheData(SystemConstant.FilePath.DATABASE_INFO_DATA_FILE_NAME, CommonData.databaseInfoList);
        return R.ok(true);
    }

    @PostMapping("/saveIgnoreWords")
    public R<Boolean> saveIgnoreWords(@RequestBody Map<String, Object> param) {
        String code = (String) param.get("code");
        String ignoreWords = (String) param.get("ignoreWords");
        // 如果为空，则清除忽略词
        if (StringUtils.isEmpty(ignoreWords)) {
            if (RegulationCheckTypeEnum.NAME_ERROR_SPELL.getCode().equals(code)) {
                if (!StringUtils.isEmpty(CommonData.ignoreSpellingWordStr)) {
                    CommonData.ignoreSpellingWordStr = "";
                    Tools.setCacheData(SystemConstant.FilePath.IGNORE_SPELLING_WORDS_DATA_FILE_NAME, CommonData.ignoreSpellingWordStr);
                }
            } else if (RegulationCheckTypeEnum.TABLE_NAME_CONTAIN_PLURALITY.getCode().equals(code)) {
                if (!StringUtils.isEmpty(CommonData.ignorePluralizeWordStr)) {
                    CommonData.ignorePluralizeWordStr = ignoreWords;
                    Tools.setCacheData(SystemConstant.FilePath.IGNORE_PLURALIZE_WORDS_DATA_FILE_NAME, CommonData.ignorePluralizeWordStr);
                }
            }
            return R.ok(true);
        }
        // 补充头尾的逗号
        if (ignoreWords.indexOf(",") != 0) {
            ignoreWords = "," + ignoreWords;
        }
        if (ignoreWords.lastIndexOf(",") != ignoreWords.length() - 1) {
            ignoreWords = ignoreWords + ",";
        }
        ignoreWords = ignoreWords.toLowerCase(Locale.ROOT);
        if (RegulationCheckTypeEnum.NAME_ERROR_SPELL.getCode().equals(code)) {
            if (!CommonData.ignoreSpellingWordStr.equals(ignoreWords)) {
                CommonData.ignoreSpellingWordStr = ignoreWords;
                Tools.setCacheData(SystemConstant.FilePath.IGNORE_SPELLING_WORDS_DATA_FILE_NAME, CommonData.ignoreSpellingWordStr);
            }
        } else if (RegulationCheckTypeEnum.TABLE_NAME_CONTAIN_PLURALITY.getCode().equals(code)) {
            if (!CommonData.ignorePluralizeWordStr.equals(ignoreWords)) {
                CommonData.ignorePluralizeWordStr = ignoreWords;
                Tools.setCacheData(SystemConstant.FilePath.IGNORE_PLURALIZE_WORDS_DATA_FILE_NAME, CommonData.ignorePluralizeWordStr);
            }
        }
        return R.ok(true);
    }

    @GetMapping("/delete")
    public R<Boolean> delete(Integer key) {
        if (key != null && key >= 0 && key < CommonData.databaseInfoList.size()) {
            try {
                CommonData.databaseInfoList.remove(key.intValue());
                Tools.setCacheData(SystemConstant.FilePath.DATABASE_INFO_DATA_FILE_NAME, CommonData.databaseInfoList);
            } catch (Exception e) {
                throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, "删除失败");
            }
        }
        return R.ok(true);
    }

    @GetMapping("/getReport")
    public R<DifferentReportBo> getReport(Integer changeKey, Integer targetKey) {
        this.checkParam(changeKey, targetKey);
        DifferentReportBo differentReport;
        try {
            differentReport = differentStructBiz.getDifferentReport(changeKey, targetKey);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException(HttpStatus.BAD_REQUEST, "操作失败");
        }
        return R.ok(differentReport);
    }

    @GetMapping("/getSql")
    public R<List<String>> getSql(String type, Integer changeKey, Integer targetKey, String tableName, String fieldName) {
        this.checkParam(changeKey, targetKey);
        List<String> sql = new ArrayList<>();
        if ("struct".equals(type)) {
            sql = differentStructBiz.getDifferentSql(changeKey, targetKey);
        } else if ("data".equals(type)) {
            if (tableName == null || tableName.trim() == "") {
                throw new BizException(HttpStatus.BAD_REQUEST, "请填写数据库表名");
            }
            sql = differentDataBiz.getDifferentDataSql(changeKey, targetKey, tableName, fieldName);
        }
        return R.ok(sql);
    }

    @GetMapping("/getCheck")
    public R<Collection<CheckReportBo>> getCheck(Integer changeKey, String checkIds) {
        if (changeKey == null || changeKey.intValue() < 0 || changeKey.intValue() >= CommonData.databaseInfoList.size()) {
            throw new BizException(HttpStatus.BAD_REQUEST, "先遣库的数据库连接信息无效");
        }
        if (StringUtils.isEmpty(checkIds)) {
            throw new BizException(HttpStatus.BAD_REQUEST, "检查项不能为空");
        }
        Collection<CheckReportBo> checkReportBoList = differentStructBiz.regulationCheck(changeKey, checkIds);
        return R.ok(checkReportBoList);
    }

    @PostMapping("/generateCodeFile")
    public R<Boolean> generateCodeFile(@RequestBody GeneratorInfoVo param) {
        boolean result = generatorBiz.generateFile(param);
        return R.ok(result);
    }

    /**
     * 检查参数是否合法
     * @param changeKey 先遣库key
     * @param targetKey 滞后库key
     */
    private void checkParam(Integer changeKey, Integer targetKey){
        if (changeKey == null || changeKey.intValue() < 0 || changeKey.intValue() >= CommonData.databaseInfoList.size()) {
            throw new BizException(HttpStatus.BAD_REQUEST, "先遣库的数据库连接信息无效");
        }
        if (targetKey == null || targetKey.intValue() < 0 || targetKey.intValue() >= CommonData.databaseInfoList.size()) {
            throw new BizException(HttpStatus.BAD_REQUEST, "滞后库的数据库连接信息无效");
        }
        if (changeKey.equals(targetKey)) {
            throw new BizException(HttpStatus.BAD_REQUEST, "数据库连接信息不能一样");
        }
    }
}
